package com.cencat.user.dto;

import com.cencat.common.enums.GrantType;
import com.cencat.common.enums.DataScope;
import com.cencat.common.enums.DataStatus;
import com.cencat.user.entity.RolePermission;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.Builder;

import jakarta.validation.constraints.*;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 角色权限关联创建DTO
 * @author cencat
 * @since 2024-01-01
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class RolePermissionCreateDTO {

    /**
     * 角色ID
     */
    @NotNull(message = "角色ID不能为空")
    @Min(value = 1, message = "角色ID必须大于0")
    private Long roleId;

    /**
     * 权限ID
     */
    @NotNull(message = "权限ID不能为空")
    @Min(value = 1, message = "权限ID必须大于0")
    private Long permissionId;

    /**
     * 授权类型（GRANT-授权，DENY-拒绝）
     */
    @NotNull(message = "授权类型不能为空")
    private GrantType grantType;

    /**
     * 数据权限范围（ALL-全部数据，DEPT-部门数据，SELF-个人数据，CUSTOM-自定义数据）
     */
    private DataScope dataScope;

    /**
     * 自定义数据权限SQL条件
     */
    @Size(max = 1000, message = "自定义数据权限SQL条件长度不能超过1000个字符")
    private String dataCondition;

    /**
     * 生效时间
     */
    private LocalDateTime effectiveTime;

    /**
     * 失效时间
     */
    private LocalDateTime expiryTime;

    /**
     * 状态（true-启用，false-禁用）
     */
    @NotNull(message = "状态不能为空")
    private DataStatus status;

    /**
     * 优先级（数值越大优先级越高）
     */
    @NotNull(message = "优先级不能为空")
    @Min(value = 0, message = "优先级不能小于0")
    @Max(value = 999, message = "优先级不能大于999")
    private Integer priority;

    /**
     * 授权人ID
     */
    @NotNull(message = "授权人ID不能为空")
    @Min(value = 1, message = "授权人ID必须大于0")
    private Long grantBy;

    /**
     * 备注
     */
    @Size(max = 500, message = "备注长度不能超过500个字符")
    private String remark;

    /**
     * 租户ID
     */
    private Long tenantId;

    /**
     * 有效期天数（用于快速设置有效期）
     */
    @Min(value = 1, message = "有效期天数必须大于0")
    @Max(value = 3650, message = "有效期天数不能超过3650天")
    private Integer validityDays;

    /**
     * 是否永久有效
     */
    private Boolean permanent;

    /**
     * 批量权限ID列表（用于批量创建）
     */
    private List<Long> permissionIds;

    /**
     * 批量角色ID列表（用于批量创建）
     */
    private List<Long> roleIds;

    /**
     * 是否覆盖已存在的关联
     */
    private Boolean overrideExisting;

    /**
     * 通知方式（EMAIL-邮件，SMS-短信，SYSTEM-系统通知）
     */
    private List<String> notifyMethods;

    /**
     * 是否发送通知
     */
    private Boolean sendNotification;

    /**
     * 自动生效（立即生效）
     */
    private Boolean autoEffective;

    /**
     * 检查有效期设置是否合法
     * @return 是否合法
     */
    public boolean isValidityPeriodValid() {
        // 如果设置了永久有效，则不能设置失效时间和有效期天数
        if (Boolean.TRUE.equals(permanent)) {
            return expiryTime == null && validityDays == null;
        }
        
        // 如果设置了有效期天数，则不能设置失效时间
        if (validityDays != null && validityDays > 0) {
            return expiryTime == null;
        }
        
        // 如果设置了生效时间和失效时间，失效时间必须晚于生效时间
        if (effectiveTime != null && expiryTime != null) {
            return expiryTime.isAfter(effectiveTime);
        }
        
        return true;
    }

    /**
     * 检查数据权限设置是否合法
     * @return 是否合法
     */
    public boolean isDataScopeValid() {
        // 如果数据权限范围为自定义，则必须提供自定义条件
        if (DataScope.CUSTOM.equals(dataScope)) {
            return dataCondition != null && !dataCondition.trim().isEmpty();
        }
        
        // 如果数据权限范围不是自定义，则不应该有自定义条件
        if (dataScope != null && !DataScope.CUSTOM.equals(dataScope)) {
            return dataCondition == null || dataCondition.trim().isEmpty();
        }
        
        return true;
    }

    /**
     * 检查批量创建参数是否合法
     * @return 是否合法
     */
    public boolean isBatchCreateValid() {
        // 不能同时设置单个权限ID和批量权限ID
        if (permissionId != null && permissionIds != null && !permissionIds.isEmpty()) {
            return false;
        }
        
        // 不能同时设置单个角色ID和批量角色ID
        if (roleId != null && roleIds != null && !roleIds.isEmpty()) {
            return false;
        }
        
        // 必须至少设置一个权限ID
        if (permissionId == null && (permissionIds == null || permissionIds.isEmpty())) {
            return false;
        }
        
        // 必须至少设置一个角色ID
        if (roleId == null && (roleIds == null || roleIds.isEmpty())) {
            return false;
        }
        
        return true;
    }

    /**
     * 检查通知方式是否合法
     * @return 是否合法
     */
    public boolean isNotifyMethodsValid() {
        if (!Boolean.TRUE.equals(sendNotification)) {
            return true; // 不发送通知时，通知方式可以为空
        }
        
        if (notifyMethods == null || notifyMethods.isEmpty()) {
            return false; // 发送通知时，必须指定通知方式
        }
        
        // 检查通知方式是否合法
        for (String method : notifyMethods) {
            if (!"EMAIL".equals(method) && !"SMS".equals(method) && !"SYSTEM".equals(method)) {
                return false;
            }
        }
        
        return true;
    }

    /**
     * 获取实际的生效时间
     * @return 生效时间
     */
    public LocalDateTime getActualEffectiveTime() {
        if (Boolean.TRUE.equals(autoEffective)) {
            return LocalDateTime.now();
        }
        return effectiveTime;
    }

    /**
     * 获取实际的失效时间
     * @return 失效时间
     */
    public LocalDateTime getActualExpiryTime() {
        if (Boolean.TRUE.equals(permanent)) {
            return null; // 永久有效
        }
        
        if (validityDays != null && validityDays > 0) {
            LocalDateTime effective = getActualEffectiveTime();
            if (effective != null) {
                return effective.plusDays(validityDays);
            } else {
                return LocalDateTime.now().plusDays(validityDays);
            }
        }
        
        return expiryTime;
    }

    /**
     * 获取实际的权限ID列表
     * @return 权限ID列表
     */
    public List<Long> getActualPermissionIds() {
        if (permissionIds != null && !permissionIds.isEmpty()) {
            return permissionIds;
        }
        
        if (permissionId != null) {
            return List.of(permissionId);
        }
        
        return List.of();
    }

    /**
     * 获取实际的角色ID列表
     * @return 角色ID列表
     */
    public List<Long> getActualRoleIds() {
        if (roleIds != null && !roleIds.isEmpty()) {
            return roleIds;
        }
        
        if (roleId != null) {
            return List.of(roleId);
        }
        
        return List.of();
    }

    /**
     * 检查是否为批量创建
     * @return 是否为批量创建
     */
    public boolean isBatchCreate() {
        return (permissionIds != null && permissionIds.size() > 1) || 
               (roleIds != null && roleIds.size() > 1);
    }

    /**
     * 获取预计创建的关联数量
     * @return 关联数量
     */
    public int getEstimatedCreateCount() {
        int permissionCount = getActualPermissionIds().size();
        int roleCount = getActualRoleIds().size();
        return permissionCount * roleCount;
    }

    /**
     * 设置快速配置 - 立即生效的永久权限
     */
    public void setQuickConfigPermanent() {
        this.autoEffective = true;
        this.permanent = true;
        this.status = DataStatus.ENABLED;
        this.grantType = GrantType.GRANT;
        this.priority = 0;
    }

    /**
     * 设置快速配置 - 立即生效的临时权限
     * @param days 有效天数
     */
    public void setQuickConfigTemporary(int days) {
        this.autoEffective = true;
        this.validityDays = days;
        this.permanent = false;
        this.status = DataStatus.ENABLED;
        this.grantType = GrantType.GRANT;
        this.priority = 0;
    }

    /**
     * 设置快速配置 - 拒绝权限
     */
    public void setQuickConfigDeny() {
        this.autoEffective = true;
        this.permanent = true;
        this.status = DataStatus.ENABLED;
        this.grantType = GrantType.DENY;
        this.priority = 999; // 拒绝权限优先级最高
    }

    /**
     * 设置数据权限 - 全部数据
     */
    public void setDataScopeAll() {
        this.dataScope = DataScope.ALL;
        this.dataCondition = null;
    }

    /**
     * 设置数据权限 - 部门数据
     */
    public void setDataScopeDept() {
        this.dataScope = DataScope.DEPT;
        this.dataCondition = null;
    }

    /**
     * 设置数据权限 - 部门及子部门数据
     */
    public void setDataScopeDeptAndSub() {
        this.dataScope = DataScope.DEPT_AND_CHILD;
        this.dataCondition = null;
    }

    /**
     * 设置数据权限 - 个人数据
     */
    public void setDataScopeSelf() {
        this.dataScope = DataScope.SELF;
        this.dataCondition = null;
    }

    /**
     * 设置数据权限 - 自定义数据
     * @param condition 自定义条件
     */
    public void setDataScopeCustom(String condition) {
        this.dataScope = DataScope.CUSTOM;
        this.dataCondition = condition;
    }

    /**
     * 设置通知配置
     * @param sendNotification 是否发送通知
     * @param methods 通知方式
     */
    public void setNotificationConfig(boolean sendNotification, String... methods) {
        this.sendNotification = sendNotification;
        if (sendNotification && methods != null && methods.length > 0) {
            this.notifyMethods = List.of(methods);
        } else {
            this.notifyMethods = null;
        }
    }

    /**
     * 验证所有参数
     * @return 验证结果
     */
    public ValidationResult validate() {
        ValidationResult result = new ValidationResult();
        
        if (!isValidityPeriodValid()) {
            result.addError("有效期设置不合法");
        }
        
        if (!isDataScopeValid()) {
            result.addError("数据权限设置不合法");
        }
        
        if (!isBatchCreateValid()) {
            result.addError("批量创建参数设置不合法");
        }
        
        if (!isNotifyMethodsValid()) {
            result.addError("通知方式设置不合法");
        }
        
        return result;
    }

    /**
     * 验证结果类
     */
    public static class ValidationResult {
        private boolean valid = true;
        private java.util.List<String> errors = new java.util.ArrayList<>();
        
        public void addError(String error) {
            this.valid = false;
            this.errors.add(error);
        }
        
        public boolean isValid() {
            return valid;
        }
        
        public java.util.List<String> getErrors() {
            return errors;
        }
        
        public String getErrorMessage() {
            return String.join("; ", errors);
        }
    }

    /**
     * 转换为实体对象
     * @return 角色权限关联实体
     */
    public RolePermission toEntity() {
        RolePermission entity = new RolePermission();
        entity.setRoleId(this.roleId);
        entity.setPermissionId(this.permissionId);
        entity.setGrantType(this.grantType != null ? this.grantType : GrantType.GRANT);
        entity.setDataScope(this.dataScope);
        entity.setDataCondition(this.dataCondition);
        entity.setEffectiveTime(getActualEffectiveTime());
        entity.setExpiryTime(getActualExpiryTime());
        entity.setStatus(this.status != null ? this.status : DataStatus.ENABLED);
        entity.setPriority(this.priority != null ? this.priority : 0);
        entity.setGrantBy(this.grantBy);
        entity.setGrantTime(LocalDateTime.now());
        entity.setRemark(this.remark);
        entity.setTenantId(this.tenantId);
        return entity;
    }

    /**
     * 创建构建器
     * @return 构建器
     */
    public static RolePermissionCreateDTOBuilder builder() {
        return new RolePermissionCreateDTOBuilder();
    }

    /**
     * 创建简单的角色权限关联DTO
     * @param roleId 角色ID
     * @param permissionId 权限ID
     * @param grantBy 授权人ID
     * @return DTO对象
     */
    public static RolePermissionCreateDTO createSimple(Long roleId, Long permissionId, Long grantBy) {
        RolePermissionCreateDTO dto = new RolePermissionCreateDTO();
        dto.setRoleId(roleId);
        dto.setPermissionId(permissionId);
        dto.setGrantBy(grantBy);
        dto.setQuickConfigPermanent();
        return dto;
    }

    /**
     * 创建临时的角色权限关联DTO
     * @param roleId 角色ID
     * @param permissionId 权限ID
     * @param grantBy 授权人ID
     * @param days 有效天数
     * @return DTO对象
     */
    public static RolePermissionCreateDTO createTemporary(Long roleId, Long permissionId, Long grantBy, int days) {
        RolePermissionCreateDTO dto = new RolePermissionCreateDTO();
        dto.setRoleId(roleId);
        dto.setPermissionId(permissionId);
        dto.setGrantBy(grantBy);
        dto.setQuickConfigTemporary(days);
        return dto;
    }

    /**
     * 创建拒绝类型的角色权限关联DTO
     * @param roleId 角色ID
     * @param permissionId 权限ID
     * @param grantBy 授权人ID
     * @return DTO对象
     */
    public static RolePermissionCreateDTO createDeny(Long roleId, Long permissionId, Long grantBy) {
        RolePermissionCreateDTO dto = new RolePermissionCreateDTO();
        dto.setRoleId(roleId);
        dto.setPermissionId(permissionId);
        dto.setGrantBy(grantBy);
        dto.setQuickConfigDeny();
        return dto;
    }

    /**
     * 创建批量角色权限关联DTO
     * @param roleIds 角色ID列表
     * @param permissionIds 权限ID列表
     * @param grantBy 授权人ID
     * @return DTO对象
     */
    public static RolePermissionCreateDTO createBatch(List<Long> roleIds, List<Long> permissionIds, Long grantBy) {
        RolePermissionCreateDTO dto = new RolePermissionCreateDTO();
        dto.setRoleIds(roleIds);
        dto.setPermissionIds(permissionIds);
        dto.setGrantBy(grantBy);
        dto.setQuickConfigPermanent();
        return dto;
    }
}